package com.fdb.efp.nls.service.impl.wsd.credit;

import com.alibaba.fastjson.JSON;
import com.fdb.efp.nls.service.facade.NlsPublicService;
import com.fdb.efp.nls.service.facade.NlsQueueSoltComnService;
import com.fdb.efp.nls.service.facade.WsApproveackConfirmService;
import com.fdb.efp.nls.service.vo.WsApproveackConfirmVO;
import com.fdb.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.fdb.efp.nls.service.vo.sx.NlsCreditInfoVO;
import com.gdrcu.efp.cus.common.CusBankRelEnum;
import com.gdrcu.efp.cus.common.CusStatusEnum;
import com.gdrcu.efp.cus.common.CusTypeEnum;
import com.fdb.basic.framework.core.base.FrameworkService;
import com.fdb.basic.framework.core.constant.CountryConstant;
import com.fdb.basic.framework.core.constant.SDicToExternalConstant;
import com.fdb.basic.framework.core.constant.SDicToLocalConstant;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.*;
import com.fdb.basic.framework.core.util.sdic.SDicToExternal;
import com.fdb.basic.framework.core.util.sdic.SDicToLocal;
import com.fdb.basic.sequence.service.facade.SequenceService;
import com.fdb.efp.nls.common.ConsoleConstant;
import com.fdb.efp.nls.service.vo.PrdInfoVO;
import com.fdb.efp.cus.service.facade.CusIndivExtService;
import com.fdb.efp.cus.service.facade.CusIndivService;
import com.fdb.efp.cus.service.vo.CusIndivExtVO;
import com.fdb.efp.cus.service.vo.CusIndivVO;
import com.fdb.efp.esb.common.constant.nls.NlsCrrEnum;
import com.fdb.efp.esb.service.bo.req.hj.ReqCusInfoCreBean;
import com.fdb.efp.esb.service.bo.req.wsd.finalnotice.FinalApproveNoticeReqBean;
import com.fdb.efp.esb.service.bo.resp.hj.RespCusInfoCreBean;
import com.fdb.efp.esb.service.bo.resp.wsd.finalnotice.FinalApproveNoticeRespBean;
import com.fdb.efp.esb.service.facade.EsbInvokeWrapper;
import com.fdb.efp.esb.service.facade.hj.CustomerInfoCreateService;
import com.fdb.efp.esb.service.facade.wsd.finalnotice.FinalApproveNoticeService;
import com.fdb.efp.nls.service.impl.sx.CreditSoltServiceImpl;
import com.fdb.efp.rule.common.enumeration.RefuseType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;


@Service("wsdCusDocumentService")
public class WsdCusDocumentServiceImpl extends CreditSoltServiceImpl implements FrameworkService {

    /**
     * 日志信息
     */
    private final Logger logger = LoggerFactory.getLogger(WsdCusDocumentServiceImpl.class);
    /**
     * 日志模板
     */
    private final String msgTemplate = "message{}";
    /**
     * 产品信息服务
     */
    @Autowired
    @Qualifier("nlsPublicService")
    private NlsPublicService nlsPublicService;
    /**
     * 客人信息服务
     */
    @Autowired
    @Qualifier("cusIndivService")
    private CusIndivService cusIndivService;
    /**
     * 客户建档接口
     */
    @Autowired
    @Qualifier("customerInfoCreateService")
    private CustomerInfoCreateService customerInfoCreateService;
    /**
     * 终审应答服务
     */
    @Autowired
    @Qualifier("finalApproveNoticeService")
    private FinalApproveNoticeService finalApproveNoticeService;

    // 告警服务
    @Autowired
    @Qualifier("nlsQueueSoltComnService")
    private NlsQueueSoltComnService nlsQueueSoltComnService;

    // 应答信息
    @Autowired
    @Qualifier("wsApproveackConfirmService")
    private WsApproveackConfirmService wsApproveackConfirmService;

    @Autowired
    @Qualifier("cusIndivExtService")
    private CusIndivExtService cusIndivExtService;

    private static final DateTimeFormatter timeStrFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    protected void doExecute(NlsProcessBizVO nlsProcessBizVo, NlsCreditInfoVO nlsCreditInfoVO) throws Exception {

        String applySeq = nlsCreditInfoVO.getLmtApplySeq();
        logger.info("======>客户建档服务开始,流水号" + applySeq+"<======");

        // 判断客户是否存在
        boolean exist = isCustomerExist(nlsCreditInfoVO);
        // 上送互金建档Bean
        RespCusInfoCreBean respCusInfoCreBean = new RespCusInfoCreBean();
        // 查询产品信息表
        PrdInfoVO prdInfoVo = nlsPublicService.getProInfo(nlsCreditInfoVO.getPrdId());
        CusIndivVO cusIndivVO = null;

        /*###################################################################################################*/
        /********************************* 客户建档插槽主流程 ************************************************/
        /*###################################################################################################*/
        try {
            // 客户不存在
            if (!exist) {
                // 上送客户建档信息至互金
                respCusInfoCreBean = pushCusToOnlineFinance(nlsCreditInfoVO);
                //插入客户表信息
                insertCustomerInfo(nlsCreditInfoVO, respCusInfoCreBean, prdInfoVo);
            } else {
                // 更新客户表信息
                cusIndivVO = updateCustomerInfo(nlsCreditInfoVO, respCusInfoCreBean, prdInfoVo);
            }
            // 更新授信申请客户id
            nlsCreditInfoVO.setCusId(Objects.isNull(respCusInfoCreBean.getUsrID()) ? cusIndivVO.getCusId() : respCusInfoCreBean.getUsrID());
            nlsProcessBizVo.setCusId(Objects.isNull(respCusInfoCreBean.getUsrID()) ? cusIndivVO.getCusId() : respCusInfoCreBean.getUsrID());
        } catch (Exception e) {
            logger.error("======>【客户建档插槽】执行失败原因为<======", e.getMessage());
            // 更新终审审批信息
            try {
                updateApproveackConfirm(nlsCreditInfoVO, e);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            nlsProcessBizVo.setExceptionFlag(Boolean.TRUE);
            nlsProcessBizVo.setRefuseMsg(RefuseType.OTHER.getMsg());
            nlsProcessBizVo.setExceptionMsg(e);
        }finally {
            logger.info("======>客户建档服务结束,流水号<======" + applySeq);
        }
    }

    private void updateApproveackConfirm(NlsCreditInfoVO nlsCreditInfoVO, Exception e) throws ESBException, InterruptedException {
        WsApproveackConfirmVO wsApproveackConfirm = nlsPublicService.getWsApproveackConfirm(nlsCreditInfoVO.getLmtApplySeq());
        // 发送终审通知
        FinalApproveNoticeReqBean finalApproveNoticeReqBean = new FinalApproveNoticeReqBean();
        finalApproveNoticeReqBean.setRqsIdmptntID(wsApproveackConfirm.getRequestId());
        finalApproveNoticeReqBean.setAplNo(wsApproveackConfirm.getApplyNo());
        finalApproveNoticeReqBean.setAdptCertNm(nlsCreditInfoVO.getCusName());
        finalApproveNoticeReqBean.setAdptCertNo(nlsCreditInfoVO.getCertCode());
        finalApproveNoticeReqBean.setCnsntFlg("N");
        finalApproveNoticeReqBean.setRjctnCd("reason_code_11");
        finalApproveNoticeReqBean.setAprvlRsltRsn("客户建档失败:"+e.getMessage());
        finalApproveNoticeReqBean.setExnFld("{}");
        EsbInvokeWrapper esbInvokeWrapper = new EsbInvokeWrapper(finalApproveNoticeService, finalApproveNoticeReqBean,nlsQueueSoltComnService);
        FinalApproveNoticeRespBean finalApproveNoticeRespBean = (FinalApproveNoticeRespBean) esbInvokeWrapper.invoke3Threes();
        // 更新终审应答信息
        wsApproveackConfirm.setRefuseCode("reason_code_11");
        wsApproveackConfirm.setAckMsg("客户建档失败:"+e.getMessage());
        wsApproveackConfirm.setResultInfo(JSON.toJSONString(finalApproveNoticeRespBean));
        wsApproveackConfirmService.updateByPk(wsApproveackConfirm);
    }

    /**
     * 设置客户基本信息: <br>
     * <p>
     * 0.1:caoxin:2019/4/24 16:50:  <br>
     * @return
     * @author caoxin
     * @date 2019/4/24 16:50
     * @version 0.1
     * @since 2019/4/24 16:50
     */

    private CusIndivVO getCusIndivVO(NlsCreditInfoVO nlsCreditInfoVO, RespCusInfoCreBean respCusInfoCreBean, PrdInfoVO prdInfoVo) {
        CusIndivVO cusIndivVO = new CusIndivVO();
        // 核心客户号为空，证明是没有走客户调客户建档，存量数据；不更新
        if (StringUtils.isEmpty(respCusInfoCreBean.getClntNo())) {
            cusIndivVO.setCusId(getCusId(nlsCreditInfoVO));
        }else {
            // 客户号-存互金用户号
            cusIndivVO.setCusId(respCusInfoCreBean.getUsrID());
            // 内部客户ID-存互金客户号
            cusIndivVO.setInnerCusId(respCusInfoCreBean.getClntNo());
        }
        // 客户姓名
        cusIndivVO.setCusName(nlsCreditInfoVO.getCusName());
        // 客户性别
        cusIndivVO.setIndivSex(ValidationUtils.getSexFromIdNumber(nlsCreditInfoVO.getCertCode()).getEnname());
        // 客户证件类型
        cusIndivVO.setCertType(nlsCreditInfoVO.getCertType());
        // 客户证件号码
        cusIndivVO.setCertCode(nlsCreditInfoVO.getCertCode());
        // 证件到期日
        cusIndivVO.setIndivIdExpDt(nlsCreditInfoVO.getCertEndDt());
        // 证件地址
        cusIndivVO.setIndivRsdAddr(nlsCreditInfoVO.getIndivRsdAddr());
        //国籍
        cusIndivVO.setIndivCountry(CountryConstant.CHN);
        //职业
        try {
            cusIndivVO.setIndivOcc(SDicToLocal.getLocalSysDicVal(SDicToLocalConstant.CRR, NlsCrrEnum.OTHER.getValue()));
        }catch (Exception e){
            e.printStackTrace();
            logger.error("外部系统字典项转网贷所需字典项出错，请核查配置文件(dicExternal.properties)！");
        }
        // 客户手机号
        cusIndivVO.setPhone(nlsCreditInfoVO.getIndivMobile());
        // 客户类别
        cusIndivVO.setCusType(CusTypeEnum.NATURAL_MAN.getCode());
        // 关联银行
        cusIndivVO.setCusBankRel(CusBankRelEnum.NORMAL.getCode());
        // 客户状态
        cusIndivVO.setCusStatus(CusStatusEnum.OFFICIAL.getCode());
        // 客户渠道
        cusIndivVO.setFstAppChannel(prdInfoVo.getPrdType());
        return cusIndivVO;
    }
    /****************************************************************************************************/
    /*********************************** 查询 ***********************************************************/
    /****************************************************************************************************/
    /**
     * 获取客户号: <br>
     * <p>
     * 0.1:caoxin:2019/4/24 17:14:  <br>
     *
     * @return
     * @author caoxin
     * @date 2019/4/24 17:14
     * @version 0.1
     * @since 2019/4/24 17:14
     */

    private String getCusId(NlsCreditInfoVO nlsCreditInfoVO) {
        // 授信申请信息不为空
        Objects.requireNonNull(nlsCreditInfoVO);
        // 通过身份证号码查询是否有该客户ID
        return cusIndivService.getCusIdByCertCode(nlsCreditInfoVO.getCertType(), nlsCreditInfoVO.getCertCode());
    }
    /****************************************************************************************************/
    /*********************************** 校验 ***********************************************************/
    /****************************************************************************************************/
    /**
     * 判断客户是否存在网贷系统: <br>
     * <p>
     * 0.1:caoxin:2019/4/22 21:15:  <br>
     * @return
     * @author caoxin
     * @date 2019/4/22 21:15
     * @version 0.1
     * @since 2019/4/22 21:15
     */

    private boolean isCustomerExist(NlsCreditInfoVO nlsCreditInfoVO) {
        String cusId = getCusId(nlsCreditInfoVO);
        if (StringUtils.isNotEmpty(cusId)) {
            logger.info("网贷已存在该客户，客户号:" + cusId);
            return true;
        } else {
            logger.info("网贷不存在该客户，客户号");
            return false;
        }
    }

    /**
     * 插入客人信息: <br>
     * <p>
     * 0.1:caoxin:2019/4/22 21:31:  <br>
     *
     * @return
     * @author caoxin
     * @date 2019/4/22 21:31
     * @version 0.1
     * @since 2019/4/22 21:31
     */

    private void insertCustomerInfo(NlsCreditInfoVO nlsCreditInfoVO, RespCusInfoCreBean respCusInfoCreBean, PrdInfoVO prdInfoVo) throws BizException {
        CusIndivVO cusIndivVO = getCusIndivVO(nlsCreditInfoVO, respCusInfoCreBean, prdInfoVo);
        cusIndivVO.setComInitLoanDate(DateUtility.getCurrAppDateStr());
        cusIndivVO.setInputDate(DateUtility.getCurrAppDateStr());
        setServerInsertDefaultProperty(cusIndivVO);
        int num1 = cusIndivService.insertCusIndiv(cusIndivVO);

        final String dateTimeString = LocalDateTime.now().format(timeStrFormatter);

        //客户信息扩展表，用于联网核查
        CusIndivExtVO cusIndivExtVO=new CusIndivExtVO();
        cusIndivExtVO.setCusId(cusIndivVO.getCusId());
        cusIndivExtVO.setOnlineVerfStatus("0");//联网核查状态 0 未核查，
        cusIndivExtVO.setCreateUser("admin");
        cusIndivExtVO.setCreateTime(dateTimeString);
        cusIndivExtVO.setLastUpdateUser("admin");
        cusIndivExtVO.setLastUpdateTime(dateTimeString);
        int num2=cusIndivExtService.insert(cusIndivExtVO);

        if (num1 == -1 || num2==-1) {
            logger.error("=========>【客户建档插槽】,插入客户信息失败!!!<========", msgTemplate);
            throw new BizException("【客户建档插槽】,插入客户信息失败!!!", msgTemplate);
        }
    }

    /**
     * 上送客户建档信息到互金进行建档: <br>
     * 0.1:caoxin:2019/4/22 21:12:  <br>
     * @return
     * @author caoxin
     * @date 2019/4/22 21:12
     * @version 0.1
     * @since 2019/4/22 21:12
     */

    private RespCusInfoCreBean pushCusToOnlineFinance(NlsCreditInfoVO nlsCreditInfoVO) throws BizException {
        ReqCusInfoCreBean reqCusInfoCreBean = new ReqCusInfoCreBean();
        // 证件类型 Y
        reqCusInfoCreBean.setCertTp(nlsCreditInfoVO.getCertType());
        // 证件号码 Y
        reqCusInfoCreBean.setCertNo(nlsCreditInfoVO.getCertCode());
        // 客户姓名 Y
        reqCusInfoCreBean.setCustNm(nlsCreditInfoVO.getCusName());
        // 详细地址
        reqCusInfoCreBean.setCtcAddr(StringUtil.replaceNullByObj(nlsCreditInfoVO.getIndivRsdAddr()));
        //证件有效期
        reqCusInfoCreBean.setIdenEfftDt(StringUtil.isNullorBank(nlsCreditInfoVO.getCertEndDt()) ? "": DateUtility.format10To8(nlsCreditInfoVO.getCertEndDt()));
        //性别
        reqCusInfoCreBean.setUserGnd(ValidationUtils.getSexFromIdNumber(nlsCreditInfoVO.getCertCode()).getEnname());
        //职业
        try {
            reqCusInfoCreBean.setCrrCd(StringUtils.isBlank(nlsCreditInfoVO.getProfession()) ? NlsCrrEnum.OTHER.getValue() : (SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.CRR, nlsCreditInfoVO.getProfession())));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("本地系统字典项转互金接口所需字典项出错，请核查配置文件(dicExternal.properties)！");
        }
        //职业补充信息（ESB公共代码文档："80000"--不便分类的其他从业人员）
        if ((NlsCrrEnum.OTHER.getValue()).equals(reqCusInfoCreBean.getCrrCd()))
            reqCusInfoCreBean.setCrrSuplCmnt("个人经营者");
        // 签发机关（默认中国）
        reqCusInfoCreBean.setIssueOrgNm(ConsoleConstant.CHINA);
        // 手机号码
        reqCusInfoCreBean.setMblNo(nlsCreditInfoVO.getIndivMobile());
        // 国籍
        try{
            reqCusInfoCreBean.setNation(StringUtils.isBlank(nlsCreditInfoVO.getNational())?
                    SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.COUNTRY, CountryConstant.CHN)
                    : SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.COUNTRY, nlsCreditInfoVO.getNational()));
        }catch (Exception e){
            e.printStackTrace();
            logger.error("本地系统字典项转互金接口所需字典项出错，请核查配置文件(dicExternal.properties)！");
        }
        // 婚姻状况
        reqCusInfoCreBean.setMrgSitu(StringUtil.replaceNullByObj(nlsCreditInfoVO.getMrgSitu()));
        // 配偶姓名
        reqCusInfoCreBean.setSpsNm(StringUtil.replaceNullByObj(nlsCreditInfoVO.getSpsNm()));
        // 机构代码
        reqCusInfoCreBean.setInstId(nlsCreditInfoVO.getNlsOperOrgid());
        // 设置平台ID
        TraceUtil.setPlafmID("R00003");
        // 产品类型
        reqCusInfoCreBean.setProdType("10002004");
        // 设置平台用户ID
        TraceUtil.setPlafmUsrID(nlsCreditInfoVO.getChannelNo()+nlsCreditInfoVO.getCertCode());
        try {
            // 推送信息到互金进行客户建档
            return customerInfoCreateService.customerInfoCreate(reqCusInfoCreBean);
        } catch (Exception e) {
            logger.error("=========>【客户建档插槽】调用互金核心客户建档异常<======" + e, msgTemplate);
            throw new BizException("【客户建档插槽】调用互金核心客户建档异常!!! "+e);
        }


    }
    /**
     * 更新授信申请表表信息: <br>
     * <p>
     * 0.1:caoxin:2019/4/22 8:23:  <br>
     *
     * @return
     * @author caoxin
     * @date 2019/4/19 8:23
     * @version 0.1
     * @since 2019/4/19 8:23
     */

    private CusIndivVO updateCustomerInfo(NlsCreditInfoVO nlsCreditInfoVO, RespCusInfoCreBean respCusInfoCreBean, PrdInfoVO prdInfoVo) throws BizException {
        CusIndivVO cusIndivVO = getCusIndivVO(nlsCreditInfoVO, respCusInfoCreBean, prdInfoVo);
        setServerUpdateDefaultProperty(cusIndivVO);
        int result = cusIndivService.updateByPk(cusIndivVO);
        if (result == -1) {
            logger.error("=========>【客户建档插槽】,更新客户信息失败!!!<======", msgTemplate);
            throw new BizException("【客户建档插槽】,更新客户信息失败!!!");
        }
        return cusIndivVO;

    }
    /**
     * 生成客户ID: <br>
     * 0.1:caoxin:2019/6/24 19:21: <br>
     * @author caoxin
     * @return
     * @since 2019/6/24 19:21
     * @date 2019/6/24 19:21
     * @version 0.1
     */
    public String getCusId() throws Exception {
        SequenceService sequenceService = (SequenceService) SpringContextUtils.getBean("dbSeqService");
        return sequenceService.getSequence("RELATION_ID", null, null);
    }


}
